package com.gzsxy.esjy.netty;


import com.gzsxy.esjy.SvConstant;
import com.gzsxy.esjy.configuration.NettyHandlerFactory;
import com.gzsxy.esjy.configuration.properties.ServerProperties;
import com.gzsxy.esjy.handler.StatusHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.util.concurrent.DefaultThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * netty启动服务
 * @author zhangxiaolong
 * @date 2022/7/5 21:36
 */
public class NettyServer extends BaseBootstrapServer{

	private static final Logger log = LoggerFactory.getLogger(NettyServer.class);

	@Autowired
	private ServerProperties config ;
	
	@Autowired
	private NettyHandlerFactory nettyHandlerFactory ;

	private EventLoopGroup bossGroup;

	private EventLoopGroup workerGroup;
    
    @Override
    public void start() {
    	init() ;
        ChannelFuture channelFuture = bootstrap.bind(config.getPort()).syncUninterruptibly().addListener(future -> {
            String logBanner = "\n"+ SvConstant.DEFAULT_BANNER;
            System.out.println(String.format(logBanner, config.getPort()));
        });
        channel = channelFuture.channel();
        channel.closeFuture().addListener(future -> {
            log.info("Netty Http Server Start Shutdown ............");
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        });
    }
    
    @Override
    public void close() {
    	if(channel != null) {
    		channel.close();
    	}
    }

	@Override
	public void init() {
	    bootstrap = new ServerBootstrap();
        //1. 创建两个线程组 bossGroup 和 workerGroup
        //2. bossGroup 只是处理连接请求 , 真正的和客户端业务处理，会交给 workerGroup完成
        //3. 两个都是无限循环
        //4. bossGroup 和 workerGroup 含有的子线程(NioEventLoop)的个数  NettyRuntime.availableProcessors()
        //   默认实际 cpu核数 * 2
	    bossGroup = new NioEventLoopGroup(config.getBossThread(), new DefaultThreadFactory("netty.server.boss", Thread.MAX_PRIORITY));
	    workerGroup = new NioEventLoopGroup(Math.max(config.getWorkerThread(), Runtime.getRuntime().availableProcessors()),new DefaultThreadFactory("netty.server.worker", Thread.MAX_PRIORITY));
        bootstrap.group(bossGroup, workerGroup);
        //使用NioSocketChannel 作为服务器的通道实现
        bootstrap.channel(NioServerSocketChannel.class);
        //设置保持活动连接状态
        bootstrap.childOption(ChannelOption.SO_KEEPALIVE,config.isKeepLive());
        bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            public void initChannel(SocketChannel ch) {
            	ChannelPipeline pipeline = ch.pipeline();
            	pipeline
                 //针对http编解码的处理类，但是这些只能处理像http get的请求,也就是数据带在url问号后面的http请求
            	.addLast("http-codec",new HttpServerCodec())
		        .addLast("decoder-httpRequest", nettyHandlerFactory.httpRequestDecoder())
		        .addLast("decoder-HttpContent", nettyHandlerFactory.httpContentDecoder())
                 //块写入写出Handler ,目的是支持异步大文件传输（）
		        .addLast("http-chunked", new ChunkedWriteHandler())
            	.addLast("status-halder", new StatusHandler());
            }
        });
	}
	
}
